#ifndef __POLL_SERVER_HPP__
#define __POLL_SERVER_HPP__

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <poll.h>
#include "Sock.hpp"

using NS_sock::Sock;

// static const int FD_NONE=-1;

class PollServer
{
    static const int NFDS=99;
private:
    uint16_t _port;
    int _listenSock;

    /*
        struct pollfd 
        {
            int   fd;       // file descriptor  // 需要"处理"的文件描述符
            short events;   // requested events // 用户告诉内核需要 "处理" 哪些 "事情"
            short revents;  //returned events   // 内核告诉用户该文件描述符哪些 "事情" 已经就绪
        }
    */
   struct pollfd *_fds; // 动态struct pollfd数组

   /*
    typedef unsigned long int nfds_t;
   */
   nfds_t _nfds; // 当前动态struct pollfd数组的长度

public:
    PollServer(const int &port)
        :_port(port)
    {
        // 1. create listenSock
        _listenSock=Sock::Socket();
        // 2. bind port and ip 
        Sock::Bind(_listenSock,_port);
        // 3. set listen state
        Sock::Listen(_listenSock);
        // 4.init fds and nfds
        // _fds=new struct pollfd[NFDS];
        _fds=static_cast<struct pollfd*>(malloc(sizeof(struct pollfd)*NFDS));
        if(nullptr==_fds)
        {
            perror("malloc fail");
            exit(6);
        }
        _nfds=NFDS;
        for(int i=0;i<_nfds;++i) { _fds[i].fd=FD_NONE; }
        // 5.fds add listenSock
        _fds[0].fd=_listenSock;
        _fds[0].events=POLLIN;
    }

    void Start()
    {
        while(true)
        {
            // int poll(struct pollfd *fds, nfds_t nfds, int timeout);
            // 1. struct pollfd *fds: 数组首元素地址,struct pollfd fds[]
            // 2. nfds_t nfds: 数组的长度
            // 3. int timeout: 等待时间(-1阻塞式等待,0非阻塞等待,>0按时等待)
            DebugPrint();
            int n =poll(_fds,_nfds,1000);
            switch(n)
            {
                case -1:
                    perror("poll error");
                    break;
                case 0:
                    std::cout<<"No file descriptor is ready"<<std::endl;
                    break;
                default:
                    std::cout<<"The file descriptor is ready , num: "<<n<<std::endl;
                    Process();
                    break;
            }
        }
    }

    void Process()
    {
        for(int i=0;i<_nfds;++i)
        {
            if(FD_NONE==_fds[i].fd) // 排除无效的fd
            {
                continue;
            }
            if((POLLIN&_fds[i].revents)!=0) // 对listenSock,acceptSock分别处理
            // if(POLLIN&_fds[i].events)
            {
                if(_listenSock==_fds[i].fd) Accepter(); // listenSock input 就绪
                else Recver(i); // acceptSock input 就绪
            }
        }
    }

    void Accepter()
    {
        uint16_t client_port;
        std::string client_ip;
        int acceptSock=Sock::Accept(_listenSock,&client_port,&client_ip); // 获取套接字fd

        int i=1;
        for(;i<_nfds;++i)
        {
            if(FD_NONE==_fds[i].fd)
            {
                break;
            }
        }

        if(i>=_nfds) // 判断是否需要扩容
        {
            struct pollfd* ptr=static_cast<struct pollfd*>(realloc(_fds,sizeof(struct pollfd)*_nfds*2));
            if(nullptr==ptr)
            {
                perror("realloc fail");
                close(acceptSock);
                return;
            }
            else
            {
                _fds=ptr;
                _nfds*=2;
                std::cout<<"fds expansion succeeded"<<std::endl;
            }
        }
        // 添加acceptSock
        _fds[i].fd=acceptSock;
        // _fds[i].events=POLLIN|POLLOUT;
        _fds[i].events=POLLIN;
        printf("[%s %d] acceptSock: %d\n",client_ip.c_str(),client_port,acceptSock);
    }

    void Recver(int pos)
    {
        
        char buffer[1024];
        int ret=recv(_fds[pos].fd,buffer,sizeof(buffer)-1,0);

        if(ret>0)
        {
            buffer[ret]=0;
            std::cout<<"sockfd: "<<_fds[pos].fd<<"# "<<buffer<<std::endl;
        }
        else if(0==ret)
        {
            // 客户端退出,我也退出
            _fds[pos].fd=FD_NONE;
            _fds[pos].events=0;
            close(_fds[pos].fd);
            std::cout<<"client close , I close too"<<std::endl;
        }
        else
        {
            // 读取失败
            perror("recv error");
            _fds[pos].fd=FD_NONE;
            _fds[pos].events=0;
            close(_fds[pos].fd);
            // std::cerr<<"recv error"<<std::endl;
        }
    }

    void DebugPrint()
    {
        std::cout << "_fd_array[]: ";
        for(int i = 0; i < _nfds; i++)
        {
            if(_fds[i].fd == FD_NONE) continue;
            std::cout << _fds[i].fd << " ";
        }
        std::cout << std::endl;
    }

    ~PollServer()
    {
        if(_listenSock>=0)
        {
            close(_listenSock);
        }
        if(_fds!=nullptr)
        {
            free(_fds);
        }
    }
};

#endif